package com.cm.log_process.log_query.service.impl;


import com.cm.log_process.log_common.config.ConfigBean;
import com.cm.log_process.log_common.entity.Log;
import com.cm.log_process.log_common.entity.PageResult;
import com.cm.log_process.log_common.entity.RequestParam;
import com.cm.log_process.log_common.reg.BusinessRegexp;
import com.cm.log_process.log_query.dao.QueryDao;
import com.cm.log_process.log_query.service.QueryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * Creator:郭兆鹏,黄鹏星,沈万龙,邓志勇
 * Date:2019/12/31
 * 思路：查询服务接口实现类
 */
@Slf4j
@Service
public class QueryServiceImpl implements QueryService {

    private static BusinessRegexp regexp = new BusinessRegexp();

    @Autowired
    private QueryDao queryDao;

    /**
     * @Date 2019/12/31
     * @Author 沈万龙
     * 作用：根据流水单号查询日志
     */
    @Override
    public PageResult<Log> findByTransId(RequestParam param) {
        //动态获取索引名
        ConfigBean.setIndexName(param.getIndexName());
        //创建Builder来创建索引对象
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        //判断类型是否为空
        if (StringUtils.isNotEmpty(param.getFileType())) {
            //已经动态修改了索引名，所以只需要业务流水号transId
            builder.must(QueryBuilders.matchQuery("transId", param.getTransId()));
            builder.must(QueryBuilders.matchQuery("fileType", param.getFileType()));
        } else {//如果类型为空，则只根据流水号查询
            builder.must(QueryBuilders.matchQuery("transId", param.getTransId()));
        }
        //创建分页对象(Es的分页api是从第0页开始的)
        Pageable pageable = PageRequest.of(param.getPageIndex() - 1, param.getPageSize());
        //设置字段的排序(按照时间戳降序排序)
        FieldSortBuilder sortBuilder = SortBuilders.fieldSort("timestamp").order(SortOrder.DESC);
        //构建查询
        SearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(builder)//将查询条件设置构建中
                .withPageable(pageable)//将分页条件设置到构建中
                .withSort(sortBuilder)//将排序设置到构建中
                .build();
        Page<Log> logPage = queryDao.search(query);
        //获取记录的总条数
        long total = logPage.getTotalElements();
        //获取记录的内容
        List<Log> content = logPage.getContent();
        return new PageResult<>(content, total);
    }


    /**
     * @Date 2019/12/12
     * @Author 黄鹏星
     * 功能: 通过电话号码查询(不带时间戳)
     */
    @Override
    public PageResult<Log> findByPhoneNum(RequestParam param) {
        //创建分页对象
        Pageable pageable = PageRequest.of(param.getPageIndex() - 1, param.getPageSize());
        //创建检索字段
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders.wildcardQuery("message", "*" + param.getPhoneNum() + "*"));
        //判断类型字段是否为空
        if (StringUtils.isNotEmpty(param.getFileType())) {
            boolQuery.filter(QueryBuilders.matchQuery("fileType", param.getFileType()));
        }
        //创建时间排序询字段
        FieldSortBuilder sortBuilder = SortBuilders.fieldSort("timestamp")
                .order(SortOrder.DESC);//降序查询
        //创建查询构建器
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQuery)
                .withSort(sortBuilder)
                .withPageable(pageable)
                .build();
        Page<Log> logPage = queryDao.search(searchQuery);
        //遍历根据正则表达式取出符合条件的日志
        List<Log> logs = getLogs(logPage);
        //返还(总记录数,内容)
        return new PageResult<>(logs, logPage.getTotalElements());
    }

    /**
     * @Date 2019/1/2
     * @Author 黄鹏星
     * 功能: 通过流水单号和电话号码查询(不带时间戳)
     */
    @Override
    public PageResult<Log> findByTransIdAndPhoneNum(RequestParam param) {
        Pageable pageable = PageRequest.of(param.getPageIndex() - 1, param.getPageSize());
        //创建查询复合条件
        BoolQueryBuilder boolQuery = new BoolQueryBuilder()
                .must(QueryBuilders.matchQuery("transId", param.getTransId())) //精确根据流水单号查询
                .must(QueryBuilders.wildcardQuery("message", "*" + param.getPhoneNum() + "*")); //模糊查询电话号码查询
        //判断是否有文件类型查询条件
        if (StringUtils.isNotEmpty(param.getFileType())) {
            boolQuery.filter(QueryBuilders.matchQuery("fileType", param.getFileType()));
        }
        //设置排序条件
        SortBuilder sortBuilder = SortBuilders.fieldSort("timestamp").order(SortOrder.DESC);
        //组装聚合查询条件
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQuery)
                .withPageable(pageable)
                .withSort(sortBuilder)
                .build();
        //进行查询
        Page<Log> logPage = queryDao.search(searchQuery);
        List<Log> logs = getLogs(logPage);//遍历根据正则表达式取出符合条件的日志
        return new PageResult<>(logs, logPage.getTotalElements());
    }

    //遍历取出符合条件的日志集合
    private List<Log> getLogs(Page<Log> search) {
        List<Log> logs = new ArrayList<>();
        for (Log el : search.getContent()) {
            if (!(el.getFileType().equalsIgnoreCase("INFO"))) {
                if (regexp.testPhoneNum(el.getMessage())) {
                    logs.add(el);
                }
            }
        }
        return logs;
    }

}
